//
//  AppDelegate.swift
//  AppDelegate全局只有一个
//  他的功能就是代理系统的一些事件
//  例如：APP后台了，前台了等事件
//
//  Created by smile on 2019/6/4.
//  Copyright © 2019 ixuea. All rights reserved.
//

import UIKit

// 导入媒体
import AVFoundation

//导入发布订阅框架
import SwiftEventBus

//导入主题框架
import SwiftTheme

//导入日志框架
import CocoaLumberjack

//导入通知框架
import UserNotifications

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    
    /// 点击的未处理通知用户信息
    var clickNotificationUserInfo:[AnyHashable : Any]?
    
    /// 播放列表管理器
    var playListManager:PlayListManager?
    
    /// 播放管理器
    var musicPlayerManager:MusicPlayerManager!
    
    /// 是否自动恢复播放
    var isRsumePlay = false
    
    /// 屏幕方向
    /// 默认为竖屏
    var orientationMask = UIInterfaceOrientationMask.portrait
    
    /// 当前聊天用户的Id
    var currentChatUserId:String?
    
    /// 定义一个静态的计算属性
    /// 返回AppDelegate对象实例
    open class var shared: AppDelegate {
        get {
            return UIApplication.shared.delegate as! AppDelegate
        }
    }
    
    /// 初始化媒体相关
    func initMedia() {
        //初始化播放列表管理器
        playListManager = PlayListManager.shared
        
        //初始化播放管理器
        musicPlayerManager = MusicPlayerManager.shared()
        
        //获取到音频会话
        let session = AVAudioSession.sharedInstance()
        
        //设置category
        //可以简单理解为：category就是预定好的一些模式
        //playback:可以后台播放；独占；音量可以控制音量
        try! session.setCategory(.playback, mode: .default, options: [])
        
        //激活音频会话
        try! session.setActive(true, options: [])
        
        //告诉系统
        //我们要接收远程控制事件
        UIApplication.shared.beginReceivingRemoteControlEvents()
        
        //设置响应者
        becomeFirstResponder()
        
        //监听其他音频中断
        //包括其他软件播放音乐
        //当然播放视频也算
        //拨打电话
        //来电
        NotificationCenter.default.addObserver(self, selector: #selector(onInterruptionChanged(notification:)), name: AVAudioSession.interruptionNotification, object: nil)
        
        //监听耳机插入和拔掉通知
        NotificationCenter.default.addObserver(self, selector: #selector(onAudioRouteChanged(notification:)), name: AVAudioSession.routeChangeNotification, object: nil)
    }
    
    /// 音频输出路径改变了回调
    ///
    /// - Parameter notification: <#notification description#>
    @objc func onAudioRouteChanged(notification:Notification) {
        let userInfo = notification.userInfo
        
        print("AppDelegate onAudioRouteChanged:\(userInfo)")
        
        //获取类型
        let type=userInfo![AVAudioSessionRouteChangeReasonKey] as! Int
        
        //判断类型
        switch type {
        case kAudioSessionRouteChangeReason_NewDeviceAvailable:
            //新增了设备
            print("AppDelegate onAudioRouteChanged new device available")
        case kAudioSessionRouteChangeReason_OldDeviceUnavailable:
            //移除了设备
            print("AppDelegate onAudioRouteChanged old device unavailable:\(PreferenceUtil.isRemoveHeadsetStopMusic())")

                //这里是子线程
                DispatchQueue.main.async {
                    //切换到主线程

                    //因为播放管理器中会回调界面

                    if PreferenceUtil.isRemoveHeadsetStopMusic(){
                        if self.musicPlayerManager.isPlaying(){
                            //有音乐正在播放

                            //暂停
                            self.playListManager?.pause()
                        }
                    }else {
                        //如果不停止
                        
                        //就继续播放
                        self.playListManager?.resume()
   
                    }
                }
            
        default:
            break
        }
    }
    
    /// 返回当前window支持的屏幕方向
    ///
    /// - Parameters:
    ///   - application: <#application description#>
    ///   - window: <#window description#>
    /// - Returns: <#return value description#>
    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        return orientationMask
    }
    
    /// 音频中断了
    /// 包括其他软件播放音频
    /// 来电话了；拨打电话等
    ///
    /// - Parameter notification: <#notification description#>
    @objc func onInterruptionChanged(notification:Notification) {
        print("AppDelegate onInterruptionChanged")
        
        //将三个变量都拆包
        //如果有一个变量拆包失败
        //就直接返回了
        guard let userInfo = notification.userInfo,
            let interruptionTypeRawValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt,
            let interruptionType = AVAudioSession.InterruptionType(rawValue: interruptionTypeRawValue) else {
            return
        }
        
        switch interruptionType {
        case .began:
            //中断事件开始
            //例如：播放电话，或者接听电话
            print("AppDelegate onInterruptionChanged began")
            
            if musicPlayerManager.isPlaying() {
                //音乐在播放
                
                //暂停
                playListManager!.pause()
                
                //自动恢复播放
                isRsumePlay = true
            }
        case .ended:
            //中断事件结束了
            //例如：挂断电话
            print("AppDelegate onInterruptionChanged ended")
            
            if isRsumePlay {
                //自动恢复播放
                playListManager!.resume()
                
                //清除自动播放标记
                isRsumePlay = false
            }
        default:
            break
        }
        
    }
    
    // MARK: - 远程控制事件
    //表示我们当前这个应用是第一响应者
    override var canBecomeFirstResponder: Bool{
        return true
    }
    
    /// 接收远程控制事件
    /// 可以接收到媒体控制中心的事件
    ///
    /// - Parameter event: <#event description#>
    override func remoteControlReceived(with event: UIEvent?) {
        print("AppDelegate remoteControlReceived:\(event?.type),\(event?.subtype)")
        
        //判断是不是远程控制事件
        if event?.type == UIEvent.EventType.remoteControl {
            //是远程控制事件
            
            //是否有音乐
            if playListManager!.data == nil {
                //当前播放列表中没有音乐
                return
            }
            
            //判断事件类型
            switch event!.subtype {
            case .remoteControlPlay:
                //点击了播放按钮
                print("AppDelegate play")
                
                playListManager!.resume()
            case .remoteControlPause:
                //点击了暂停
                print("AppDelegate pause")
                
                playListManager!.pause()
            case .remoteControlNextTrack:
                //下一首
                //双击iPhone有线耳机上的控制按钮
                print("AppDelegate next")
                
                if playListManager!.getPlayList().count > 0{
                    playListManager!.play(playListManager!.next())
                }
            case .remoteControlPreviousTrack:
                //上一首
                //三击iPhone有线耳机上的控制按钮
                print("AppDelegate previouse")
                
                playListManager!.play(playListManager!.previous())
            case .remoteControlTogglePlayPause:
                //单击iPhone有线耳机上的控制按钮
                print("AppDelegate toggle play pause")
                
                //播放或者暂停
                playOrPause()
            default:
                break
            }
        }
        
        
    }
    
    /// link恢复回调方法
    /// - Parameters:
    ///   - application:
    ///   - userActivity:
    ///      userActivity.webpageURL
    ///        对于前面配置的videos/1，该值为：https://dev-courses-misuc.ixuea.com/mycloudmusic/videos/1
    ///   - restorationHandler:
    /// - Returns: true表示您的应用程序处理了活动，false您的应用程序没有处理活动。
    func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
        
        // 获取解析userActivity.webpageURL
        //如果解析失败，可以认为该次启动，应用不用处理
        guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
              let incomingURL = userActivity.webpageURL,
              let components = NSURLComponents(url: incomingURL, resolvingAgainstBaseURL: true) else {
            return false
        }
        
        // 检查是否有path，对于我们这里，必须要有才能处理
        guard let path = components.path else { return false }
        
        //对于前面配置的videos/1，值为：/mycloudmusic/videos/1
        DDLogDebug("AppDelegate continue userActivity path=\(path)")
        
        if userActivity.webpageURL?.absoluteString.contains(find: "pay") ?? false {
            //微信支付回调
            return WXApi.handleOpenUniversalLink(userActivity, delegate: self)
        }
        
        //现在要做的是，就是根据路径匹配处理具体是做什么，这里就不在实现了
        
        return true
        
    }
    
    /// 播放或暂停
    func playOrPause() {
        if musicPlayerManager.isPlaying() {
            playListManager!.pause()
        } else {
            playListManager!.resume()
        }
    }
    
    // MARK: - 用户相关
    /// 退出方法
    func logout() {
        //如果需要调用退出接口
        //就在这里调用就行了
        
        //清除用户信息
        PreferenceUtil.logout()
        
        //清除第三方登录的token
        //清除微信
        ShareSDK.cancelAuthorize(.typeWechat, result: nil)
        
        //清除QQ
        ShareSDK.cancelAuthorize(.typeQQ, result: nil)
        
        //清除微博
        ShareSDK.cancelAuthorize(.typeSinaWeibo, result: nil)
        
        //跳转到登录注册页面
        toLoginOrRegister()
        
        //通知退出成功
        onLogout()
    }
    
    /// 当用户退出了
    func onLogout() {
       //退出聊天服务器
        JMSGUser.logout(nil)
    }
    
    /// 当用户登录了
    func onLogin(_ data:Session)  {
        //登录聊天服务
        let id=StringUtil.wrapperUserId(data.user)
        JMSGUser.login(withUsername: id, password: id) { (_ , error) in
            if let error=error{
                print("AppDelegate message login failed:\(data.user),\(error)")
            }else{
                print("AppDelegate message login succes:\(data.user)")
            }
        }
        
        //保存用户登录后的信息
        PreferenceUtil.setUserId(data.user)
        PreferenceUtil.setUserToken(data.session)
        
        //跳转到首页
        toHome()
    }
    
    /// 设置跟控制器
    ///
    /// - Parameter name: <#name description#>
    func setRootViewController(name:String) {
        //获取到Main.storyboard
        let mainStory=UIStoryboard(name: "Main", bundle: nil)
        
        //实例化Guide场景
        //因为场景关联了控制器
        //所以说也可以说实例化了一个控制
        //只是这个过程是系统创建的
        //不是我们手动完成
        let controller=mainStory.instantiateViewController(withIdentifier: name)
        
        //替换掉原来的根控制器
        //目的是，我们不希望用户还能返回到启动界面
        window!.rootViewController=controller
    }

    /// 跳转到引导界面
    func toGuide() {
//        //获取到Main.storyboard
//        let mainStory=UIStoryboard(name: "Main", bundle: nil)
//
//        //实例化Guide场景
//        //因为场景关联了控制器
//        //所以说也可以说实例化了一个控制
//        //只是这个过程是系统创建的
//        //不是我们手动完成
//        let controller=mainStory.instantiateViewController(withIdentifier: "Guide")
//
//        //替换掉原来的根控制器
//        //目的是，我们不希望用户还能返回到启动界面
//        window!.rootViewController=controller
        
        setRootViewController(name: "Guide")
    }
    
    /// 跳转到登录/注册界面
    func toLoginOrRegister() {
//        //获取到Main.storyboard
//        let mainStory=UIStoryboard(name: "Main", bundle: nil)
//
//
//        //实例化场景
//        let controller=mainStory.instantiateViewController(withIdentifier: "LoginOrRegister")
//
//        //替换掉原来的根控制器
//        window!.rootViewController=controller
        
//        setRootViewController(name: "LoginOrRegister")
        
        setRootViewController(name: "LoginOrRegisterNavigation")
    }
    
    /// 显示启动界面后的广告界面
    func toAd() {
        //可以看到使用自定义的方法
        //要启动一个界面就非常简单了
        setRootViewController(name: "Ad")
    }

    /// 跳转到首页
    func toHome(_ adUri:String?=nil) {
        print("AppDelegate toHome:\(adUri)")
        
        //初始化通知
        initNotification()
        
        //初始化媒体
        initMedia()
        
        //监听聊天未读消息数改变了
        SwiftEventBus.onMainThread(self, name: ON_MESSAGE_COUNT_CHANGED) { (sender) in
            self.showApplicationBadge()
        }
        
        showApplicationBadge()
        
//        //获取到Main.storyboard
//        let mainStory=UIStoryboard(name: "Main", bundle: nil)
//
//        //实例化场景
//        let controller=mainStory.instantiateViewController(withIdentifier: "Home")
//
//        //替换掉原来的根控制器
//        window!.rootViewController=controller
        
        setRootViewController(name: "Home")
        
        if let adUri = adUri {
            //如果有广告地址
            //才发送一个通知
            
            //为什么要发送通知呢？
            //其实是因为我们在AppDelegate中
            //不太好拿到发现界面控制器
            DispatchQueue.main.async {
                NotificationCenter.default.post(name: NSNotification.Name(rawValue: AD_CLICK), object: nil, userInfo: ["adUri":adUri])
            }
        }
    }
    
    /// 显示桌面图标角标
    func showApplicationBadge() {
        UIApplication.shared.applicationIconBadgeNumber=MessageUtil.getUnreadMessageCount()
    }
    
    /// 初始化SharedSDK
    func initSharedSDK() {
        ShareSDK.registPlatforms { register in
            //设置微信信息
            register?.setupWeChat(withAppId: WECHAT_APP_ID, appSecret: WECHAT_APP_SECRET, universalLink: APP_UNIVERSAL_LINK)
            
            //设置QQ信息
            register?.setupQQ(withAppId: QQ_APP_ID, appkey: QQ_APP_SECRET,enableUniversalLink: false,universalLink: APP_UNIVERSAL_LINK)
            
            //配置微博
            register?.setupSinaWeibo(withAppkey: WEIBO_APP_KEY, appSecret: WEIBO_APP_SECRET, redirectUrl: WEIBO_REDIRECT_URI, universalLink: APP_UNIVERSAL_LINK)
            
        }
    }
    
    /// 初始化TabBar
    func initTabBar() {
        //TabBar选中高亮颜色
        UITabBar.appearance().tintColor = UIColor(hex: COLOR_PRIMARY)
    }
    
    /// 初始化高德地图
    func initAMap() {
        AMapServices.shared()?.apiKey=AMAP_KEY
    }
    
    /// 设置主题
    ///
    /// - Parameter isNight: <#isNight description#>
    func setNight(_ isNight:Bool) {
        //0:表示主题数组中第1个元素,白天
        //1:表示椎体数组中的2个元素,夜间
        ThemeManager.setTheme(index: isNight ? 1:0)
    }
    
    /// 初始化主题
    func initTheme() {
        setNight(PreferenceUtil.isNight())
    }
    
    /// 初始化日志
    func initLog() {
//        //日志打印到控制器
//        DDLog.add(DDOSLogger.sharedInstance)
//
//        //打印到文件
//        let fileLogger = DDFileLogger()
//
//        //每个文件保存24小时日志
//        //其实就是保存每天日志到一个文件
//        fileLogger.rollingFrequency = 60 * 60 * 24
//
//        //保存最近7天日志
//        fileLogger.logFileManager.maximumNumberOfLogFiles = 7
//
//        //将配置添加到日志框架
//        DDLog.add(fileLogger)
        
        //定制日志规则
        if DEBUG{
            //调试模式加日志打印到控制台
            let ddosLogger=DDOSLogger.sharedInstance
            
            //设置日志格式化器
            setLogFormat(ddosLogger!)
            
            DDLog.add(ddosLogger!)
        }
        
        //所有环境
        //都打印到文件
        let fileLogger = DDFileLogger()
        
        //每个文件保存24小时日志
        //其实就是保存每天日志到一个文件
        fileLogger.rollingFrequency=60 * 60 * 24
        
        //总共保存最近30天日志文件
        fileLogger.logFileManager.maximumNumberOfLogFiles=30
        
        //设置日志格式化器
        setLogFormat(fileLogger)
        
        //只保存警告以及以上级别的日志
        DDLog.add(fileLogger, with: .warning)
        
        //使用日志API打印日志
        DDLogVerbose("AppDelegate initLog Ixuea Verbose")
        DDLogDebug("AppDelegate initLog Ixuea Debug")
        DDLogInfo("AppDelegate initLog Ixuea Info")
        DDLogWarn("AppDelegate initLog Ixuea Warn")
        DDLogError("AppDelegate initLog Ixuea Error")
        
        //打印日志时指定级别
        DDLogError("AppDelegate initLog Ixuea Error", level: .error)
        
        //获取日志保存文件夹
        let logsDirectory=fileLogger.logFileManager.logsDirectory
        print("AppDelegate log path:\(logsDirectory)")
        
        //获取排序后的日志文件名称
        let logFilenames=fileLogger.logFileManager.sortedLogFileNames
        print("AppDelegate log files:\(logFilenames)")
    }
    
    /// 设置日志格式化器
    ///
    /// - Parameter logger: <#logger description#>
    func setLogFormat(_ logger:DDAbstractLogger) {
        //设置日志格式
        
        //可以根据版本设置不同的格式
        //例如：debug模式下
        //日志格式信息更丰富，可以有方法名
        //行号；这样更容易查找错误
        
        //release：格式更紧凑，只留有用的信息
        logger.logFormatter = LogFormat()
    }
    
    /// 初始化腾讯Bugly
    func initBugly() {
        //简单的初始化
//        Bugly.start(withAppId: BUGLY_APP_KEY)
        
        //复杂初始化
        let config=BuglyConfig()
        config.debugMode = DEBUG
        Bugly.start(withAppId: BUGLY_APP_KEY, config: config)
    }
    
    /// 初始化极光服务
    func initJiGuang(_ launchOptions:[UIApplication.LaunchOptionsKey: Any]?) {
        //添加极光聊天回调
        JMessage.add(self, with: nil)
        
        //初始化极光聊天
        JMessage.setupJMessage(launchOptions, appKey: JIGUANG_APP_KEY, channel: CHANNEL, apsForProduction: true, category: nil, messageRoaming: false)
        
        //极光统计
        let config=JANALYTICSLaunchConfig()
        
        //设置AppKey
        config.appKey=JIGUANG_APP_KEY
        
        //渠道
        config.channel=CHANNEL
        
        //初始化
        JANALYTICSService.setup(with: config)
        
        //设置调试模式
        JANALYTICSService.setDebug(DEBUG)
        
        //注册 APNs 通知
        if #available(iOS 8, *) {
            JMessage.register(
                forRemoteNotificationTypes: UIUserNotificationType.badge.rawValue |
                    UIUserNotificationType.sound.rawValue |
                    UIUserNotificationType.alert.rawValue,
                categories: nil)
        } else {
            // iOS 8 以前 categories 必须为nil
            JMessage.register(
                forRemoteNotificationTypes: UIRemoteNotificationType.badge.rawValue |
                    UIRemoteNotificationType.sound.rawValue |
                    UIRemoteNotificationType.alert.rawValue,
                categories: nil)
        }
    }
    
    /// 初始化通知
    func initNotification() {
        //获取通知中心
        let center=UNUserNotificationCenter.current()
        
        //设置代理
        center.delegate=self
        
        //iOS 10以及以上版本使用以下方法注册
        //才能得到授权，注册通知以后
        //会自动注册 deviceToken
        //如果获取不到 deviceToken Xcode8下要注意开启 Capability->Push Notification
        //开启Push Notification
        //需要付费的开发者Id
        //因为我们没有付费开发者账号
        //所以一下注册肯定是会失败的
        center.requestAuthorization(options: [UNAuthorizationOptions.alert,UNAuthorizationOptions.sound, .badge]) { (granted, error) in
            if granted {
                print("AppDelegate initNotification notification granted")
            }else{
                print("AppDelegate initNotification notification not grant")
            }
        }
    }
    
    /// 应用启动时
    /// 全局只调用一次
    ///
    /// - Parameters:
    ///   - application: <#application description#>
    ///   - launchOptions: <#launchOptions description#>
    /// - Returns: <#return value description#>
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    
        //初始化日志
        initLog()
        
        //初始化腾讯Bugly
        initBugly()
        
        //初始化极光服务
        initJiGuang(launchOptions)
        
        //初始化主题
        initTheme()
        
        //微信log，在register之前打开log, 后续可以根据log排查问题
        if DEBUG {
            WXApi.startLog(by: .detail) { data in
                print("AppDelegate wechat log \(data)")
            }
        }
        
        //初始化SharedSDK
        initSharedSDK()
        
        //手动注册微信
        //微信官方sdk集成文档：https://developers.weixin.qq.com/doc/oplatform/Mobile_App/Access_Guide/iOS.html
        //微信支付官方集成文档：https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5
        WXApi.registerApp(WECHAT_APP_ID, universalLink: APP_UNIVERSAL_LINK)
        
        //使用微信提供的方法，检查UniversalLink是否配置正确
//        if DEBUG {
//            WXApi.checkUniversalLinkReady { (step, result) in
//                DDLogDebug("AppDelegate wechat checkUniversalLinkReady \(step.rawValue),\(result.success),\(result.errorInfo),\(result.suggestion)")
//            }
//        }
        
        //初始化TabBar
//        initTabBar()
        
        //初始化高德地图
        initAMap()
        
        //判断是否是点击通知启动的应用
        //这里不能直接启动界面，因为我们这里的应用结构是，还要显示启动界面，广告，然后才进入主界面
        //解决方法是把当前通知保存到AppDelegate，进入了发现界面后，在判断是否有推送消息
        //如果有，再跳转到相应的界面
        if let notificationInfo = launchOptions?[UIApplication.LaunchOptionsKey.remoteNotification] as? [AnyHashable:Any],let userInfo=notificationInfo[CUSTOM_KEY] as?  [AnyHashable:Any]{
            //应用杀死了，远程通知点击
            clickNotificationUserInfo = userInfo
        }else if let notificationInfo = launchOptions?[UIApplication.LaunchOptionsKey.localNotification] as? UILocalNotification,
                 let userInfo = notificationInfo.userInfo?[CUSTOM_KEY] as? [AnyHashable:Any]{
            //应用杀死了，本地通知点击
            clickNotificationUserInfo = userInfo
        }
        
        return true
    }

    func applicationWillResignActive(_ application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }

    func applicationWillEnterForeground(_ application: UIApplication) {
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

    /// 当应用被终止时
    ///
    /// - Parameter application: <#application description#>
    func applicationWillTerminate(_ application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
        print("AppDelegate applicationWillTerminate")
        
        //应用被杀掉后
        //保存当前音乐信息
        //其他包括了进度
        //时长
        //用于继续播放
        playListManager?.saveSong()
    }


    /// 当其他应用唤醒当前应用的时候调用
    ///
    /// - Parameters:
    ///   - app: <#app description#>
    ///   - url: <#url description#>
    ///   - options: <#options description#>
    /// - Returns: <#return value description#>
    open func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        print("AppDelegate open url:\(url)")
        
        if url.host=="safepay" {
            //支付宝客户端回调
            
            //如果手机中安装了支付宝客户端
            //跳转到支付宝客户端的支付结果从这里获取
            AlipaySDK.defaultService()!.processOrder(withPaymentResult: url) { (data) in
                print("AppDelegate open url alipay callback:\(url),data:\(data)")
                
                //将支付状态发布出去
                SwiftEventBus.post(ON_ALIPAY_CALLBACK, sender: data as! [String:Any])
            }

        }else if url.host == "pay"{
            //微信支付回调
            
            //当universal link无法正常工作室目前微信支付会回调此方法
            //处理逻辑和支付宝差不多
            //wx672a5ce2ea3a3f48://pay/?returnKey=&ret=-2
            return WXApi.handleOpen(url, delegate: self)
        }
        
        return true
    }
    
    /// 其它应用通过调用你的app中设置的URL scheme打开你的应用、例如做分享回调到自己app就调用这个方法
    /// - Parameters:
    ///   - application: <#application description#>
    ///   - url: <#url description#>
    /// - Returns: <#description#>
    func application(_ application: UIApplication, handleOpen url: URL) -> Bool {
        return WXApi.handleOpen(url, delegate: self)
    }
    
    /// 获取到了deviceToken回调方法
    /// - Parameters:
    ///   - application: <#application description#>
    ///   - deviceToken: <#deviceToken description#>
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        DDLogDebug("AppDelegate didRegisterForRemoteNotificationsWithDeviceToken")
        JMessage.registerDeviceToken(deviceToken)
    }
    
    
    /// 处理通知点击
    /// - Parameter userInfo: <#userInfo description#>
    func processNotificationClick(_ userInfo:[AnyHashable:Any]) {
        if let action = userInfo[ACTION_KEY] as? String {
            if action == ACTION_MESSAGE{
                //聊天消息
                
                //获取用户Id
                let userId=userInfo[EXTRA_ID] as! String
                
                //获取到TabBarController
                let tabBarController=self.window!.rootViewController as! UITabBarController
                
                //获取到navigationController
                //先获取到TabBar里面所有的控制器
                //然后获取当前选中的控制器
                let navigationController=tabBarController.viewControllers![tabBarController.selectedIndex] as! UINavigationController
                
                //跳转到聊天界面
                ChatController.start(navigationController, userId)
                
            }
//            else if {
//
//            }
        }
    }
    
    /// 检查是否需要处理通知点击
    func checkIfProcessNotificationClick() {
        if let userInfo = clickNotificationUserInfo {
            processNotificationClick(userInfo)
            clickNotificationUserInfo=nil
        }
    }
}

// MARK: - 极光聊天代理
extension AppDelegate:JMessageDelegate{
    
    /// 聊天框架中数据库开始升级回调
    func onDBMigrateStart() {
        print("AppDelegate onDBMigrateStart")
    }
    
    /// 极光聊天在线消息回调
    ///
    /// - Parameters:
    ///   - message: <#message description#>
    ///   - error: <#error description#>
    func onReceive(_ message: JMSGMessage!, error: Error!) {
        print("AppDelegate onReceiver:\(message.contentType),\(message.content)")
        
        //判断是否消息消息到通知栏
        let user=message.fromUser
        if user.username == currentChatUserId {
            //正在和这个人聊天
            print("AppDelegate onReceive not show notification")
        } else {
            // 显示消息到通知栏
            print("AppDelegate onReceive show notification")
            
            NotificationUtil.showMessage(message)
            
            //发送消息数改变通知
            EventBusUtil.postMessageCountChanged()
        }

    }
}

// MARK: - 系统通知代理
extension AppDelegate:UNUserNotificationCenterDelegate{
    /// 用户点击通知打开应用前
    ///
    /// - Parameters:
    ///   - center: <#center description#>
    ///   - response: <#response description#>
    ///   - completionHandler: <#completionHandler description#>
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        //处理通知
        print("AppDelegate didReceive")
        
        //根据自定义信息，处理点击事件
        if let customInfo = response.notification.request.content.userInfo[CUSTOM_KEY] as? [AnyHashable : Any] {
//            clickNotificationUserInfo=customInfo
            processNotificationClick(customInfo)
        }
        
        //处理完成后调用completionHandler完成后续操作
        completionHandler()
    }
    
    /// 在展示通知前回调
    /// 可以修改通知
    ///
    /// 本地，远程通知都会调用
    ///
    /// - Parameters:
    ///   - center: <#center description#>
    ///   - notification: <#notification description#>
    ///   - completionHandler: <#completionHandler description#>
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        
        //处理通知
        print("AppDelegate willPresent")
        
        if notification.request.trigger is UNPushNotificationTrigger {
            //远程推送的通知，不手动显示

            //在后台后，他会自动显示
        } else {
            //处理完成后一定要调用completionHandler
            completionHandler([.alert,.sound,.badge])
        }
    
    }
}

//实现微信支付协议
extension AppDelegate:WXApiDelegate{
    /// 收到一个来自微信的请求，异步处理完成后必须调用sendResp发送处理结果给微信。
    /// 可能收到的请求有GetMessageFromWXReq、ShowMessageFromWXReq等。
    /// - Parameter req: <#req description#>
    func onReq(_ req: BaseReq) {
        print("AppDelegate onReq \(req)")
    }
    
    /// 收到一个来自微信的处理结果。调用一次sendReq后会收到onResp。
    /// 可能收到的处理结果有SendMessageToWXResp、SendAuthResp等。
    /// - Parameter resp: <#resp description#>
    func onResp(_ resp: BaseResp) {
        print("AppDelegate onResp \(resp)")
        
        //判断响应类型
        if resp is PayResp {
            //支付结果通知
            
            //将支付状态发送出出去
            SwiftEventBus.post(ON_WECHATA_PAY_CALLBACK,sender: resp)
        }
    }
}
